package org.gd.hellojavacore.patterns.proxy;

import org.gd.hellojavacore.patterns.StructurePattern;

/**
 <pre>

 Шаблон Proxy (определяет объект-заместитель англ. surrogate иначе -заменитель англ. placeholder) —
 шаблон проектирования, который предоставляет объект, который контролирует доступ к другому объекту,
 перехватывая все вызовы (выполняет функцию контейнера).

 Цель

 Проблема
 Необходимо управлять доступом к объекту так, чтобы создавать громоздкие объекты «по требованию».

 Решение
 Создать суррогат громоздкого объекта. «Заместитель» хранит ссылку, которая позволяет заместителю
 обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект»,
 если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта»
 идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта»,
 контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта».
 «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс, так,
 что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект».
 При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».

 Шаблон proxy бывает нескольких видов, а именно:

 1. Протоколирующий прокси : сохраняет в лог все вызовы «Субъекта» с их параметрами.

 2. Удаленный заместитель (англ. remote proxies) : обеспечивает связь с «Субъектом», который находится
 в другом адресном пространстве или на удалённой машине. Так же может отвечать за кодирование запроса и его аргументов и отправку закодированного запроса реальному «Субъекту»,

 3. Виртуальный заместитель (англ. virtual proxies): обеспечивает создание реального «Субъекта» только
 тогда, когда он действительно понадобится. Так же может кэшировать часть информации о реальном «Субъекте», чтобы отложить его создание,

 4. Копировать-при-записи: обеспечивает копирование «субъекта» при выполнении клиентом определённых
 действий (частный случай «виртуального прокси»).

 5. Защищающий заместитель (англ. protection proxies): может проверять, имеет ли вызывающий объект
 необходимые для выполнения запроса права.

 6. Кэширующий прокси: обеспечивает временное хранение результатов расчёта до отдачи их множественным клиентам,
 которые могут разделить эти результаты.

 7. Экранирующий прокси: защищает «Субъект» от опасных клиентов (или наоборот).

 8. Синхронизирующий прокси: производит синхронизированный контроль доступа к «Субъекту» в асинхронной
 многопоточной среде.

 9. Smart reference proxy: производит дополнительные действия, когда на «Субъект» создается ссылка,
 например, рассчитывает количество активных ссылок на «Субъект».



 Преимущества и недостатки от применения

 Преимущества:

 1. удаленный заместитель;
 2. виртуальный заместитель может выполнять оптимизацию;
 3. защищающий заместитель;
 4. "умная" ссылка;
 5. Недостатки
 6. резкое увеличение времени отклика.

 Сфера применения

 Шаблон Proxy может применяться в случаях работы с сетевым соединением, с огромным объектом
 в памяти (или на диске) или с любым другим ресурсом, который сложно или тяжело копировать.
 Хорошо известный пример применения — объект, подсчитывающий число ссылок.

 Прокси и близкие к нему шаблоны:

 1. Адаптер обеспечивает отличающийся интерфейс к объекту.
 2. Прокси обеспечивает тот же самый интерфейс.
 3. Декоратор обеспечивает расширенный интерфейс

 @see org.gd.hellojavacore.patterns.adapter.Adapter
 @see org.gd.hellojavacore.patterns.proxy.Proxy
 @see org.gd.hellojavacore.patterns.decorator.Decorator

 </pre>
 */
public class Proxy implements StructurePattern {

    public static void main(String[] args) {
        // Create math proxy
        IMath p = new MathProxy();

        // Do the math
        System.out.println("4 + 2 = " + p.add(4, 2));
        System.out.println("4 - 2 = " + p.sub(4, 2));
        System.out.println("4 * 2 = " + p.mul(4, 2));
        System.out.println("4 / 2 = " + p.div(4, 2));
    }
}

